﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TargetSystemRepository.cs" company="Elilink">
//   Defor
// </copyright>
// <summary>
//   Class TargetSystemRepository
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace DataAccessLayer.Repositories.Static
{
    using System.Collections.Generic;
    using System.Linq;

    using BusinessLayer.Enums;
    using BusinessLayer.Objects;
    using BusinessLayer.Results;

    using DataAccessLayer.Repositories.Abstract;
    using DataAccessLayer.StaticTools;

    /// <summary>
    ///     Class TargetSystemRepository
    /// </summary>
    public class TargetSystemRepository : ITargetSystemRepository
    {
        #region Public Methods and Operators

        /// <summary>
        /// Adds the target system.
        /// </summary>
        /// <param name="targetSystem">
        /// The target system.
        /// </param>
        /// <returns>
        /// The <see cref="OperationResult"/>.
        /// </returns>
        public OperationResult AddTargetSystem(TargetSystem targetSystem)
        {
            if (string.IsNullOrEmpty(targetSystem.TargetSystemName))
            {
                return new OperationResult(
                    ErrorType.TargetSystemNameNotSpecified, 
                    "Can't add target system without name.");
            }

            if (StaticDatabase.TargetSystems.FirstOrDefault(t => t.TargetSystemName == targetSystem.TargetSystemName)
                != null)
            {
                return new OperationResult(
                    ErrorType.AlreadyExists, 
                    string.Format("Target '{0}' already exists.", targetSystem.TargetSystemName));
            }

            StaticDatabase.TargetSystems.Add(targetSystem);
            foreach (DeployableProject project in targetSystem.DeployableProjects)
            {
                project.TargetSystemName = targetSystem.TargetSystemName;
                DeployableProjectOperations.AddDeployableProject(project);
            }

            return new OperationResult(true);
        }

        /// <summary>
        ///     Deletes all target systems.
        /// </summary>
        /// <returns>The <see cref="OperationResult"/>.</returns>
        public OperationResult DeleteAllTargetSystems()
        {
            StaticDatabase.TargetSystems.RemoveAll(t => true);
            StaticDatabase.DeployableProjects.RemoveAll(p => true);
            return new OperationResult(true);
        }

        /// <summary>
        /// Deletes the target system.
        /// </summary>
        /// <param name="targetSystemName">
        /// Name of the target system.
        /// </param>
        /// <returns>
        /// The <see cref="OperationResult"/>.
        /// </returns>
        public OperationResult DeleteTargetSystem(string targetSystemName)
        {
            TargetSystem old = StaticDatabase.TargetSystems.FirstOrDefault(t => t.TargetSystemName == targetSystemName);
            if (old == null)
            {
                return new OperationResult(
                    ErrorType.ObjectNotFound, 
                    string.Format("Can't find target '{0}'", targetSystemName));
            }

            StaticDatabase.TargetSystems.Remove(old);
            StaticDatabase.DeployableProjects.RemoveAll(p => p.TargetSystemName == targetSystemName);
            return new OperationResult(true);
        }

        /// <summary>
        ///     Disposes the context.
        /// </summary>
        public void DisposeContext()
        {
            StaticDatabase.DeployableProjects.RemoveAll(p => true);
            StaticDatabase.TargetSystems.RemoveAll(t => true);
        }

        /// <summary>
        ///     Gets the target systems.
        /// </summary>
        /// <returns>List of <see cref="TargetSystem"/>.</returns>
        public List<TargetSystem> GetTargetSystems()
        {
            List<TargetSystem> systems = StaticDatabase.TargetSystems;
            foreach (TargetSystem targetSystem in systems)
            {
                targetSystem.DeployableProjects =
                    StaticDatabase.DeployableProjects.Where(p => p.TargetSystemName == targetSystem.TargetSystemName)
                        .ToList();
            }

            return systems;
        }

        /// <summary>
        /// Updates the target system. Updates only Build configuration!!
        /// </summary>
        /// <param name="targetSystem">
        /// The target system.
        /// </param>
        /// <returns>
        /// The <see cref="OperationResult"/>.
        /// </returns>
        public OperationResult UpdateTargetSystem(TargetSystem targetSystem)
        {
            TargetSystem old =
                StaticDatabase.TargetSystems.FirstOrDefault(t => t.TargetSystemName == targetSystem.TargetSystemName);
            if (old == null)
            {
                return new OperationResult(
                    ErrorType.ObjectNotFound, 
                    string.Format("Can't find target '{0}'", targetSystem.TargetSystemName));
            }

            old.BuildConfiguration = targetSystem.BuildConfiguration;
            return new OperationResult(true);
        }

        /// <summary>
        /// Updates the target system. Updates only Build configuration!! If old name is not equal to current - also names for
        ///     target system and dependant projects will be changed
        /// </summary>
        /// <param name="targetSystem">
        /// The target system.
        /// </param>
        /// <param name="oldTargetSystemName">
        /// Old name of the target system.
        /// </param>
        /// <returns>
        /// The <see cref="OperationResult"/>.
        /// </returns>
        public OperationResult UpdateTargetSystemWithName(TargetSystem targetSystem, string oldTargetSystemName)
        {
            TargetSystem old =
                StaticDatabase.TargetSystems.FirstOrDefault(t => t.TargetSystemName == oldTargetSystemName);
            if (old == null)
            {
                return new OperationResult(
                    ErrorType.ObjectNotFound, 
                    string.Format("Can't find target '{0}'", targetSystem.TargetSystemName));
            }

            old.BuildConfiguration = targetSystem.BuildConfiguration;
            if (!string.Equals(oldTargetSystemName, targetSystem.TargetSystemName))
            {
                if (string.IsNullOrEmpty(targetSystem.TargetSystemName))
                {
                    return new OperationResult(
                        ErrorType.TargetSystemNameNotSpecified, 
                        "Can't add target system without name.");
                }

                if (StaticDatabase.TargetSystems.FirstOrDefault(
                    t => t.TargetSystemName == targetSystem.TargetSystemName) != null)
                {
                    return new OperationResult(
                        ErrorType.AlreadyExists, 
                        string.Format("Target '{0}' already exists.", targetSystem.TargetSystemName));
                }

                old.TargetSystemName = targetSystem.TargetSystemName;
                foreach (DeployableProject deployableProject in
                    StaticDatabase.DeployableProjects.Where(p => p.TargetSystemName == oldTargetSystemName))
                {
                    deployableProject.TargetSystemName = targetSystem.TargetSystemName;
                }
            }

            return new OperationResult(true);
        }

        #endregion
    }
}